package Problema_drumurilor;

import java.util.Stack;


public class MotorCautare {
	protected final int MAX=100;
	protected Ruta rute[]=new Ruta[MAX];
	protected int nrRute=0;
	protected int distantaM=0;
	protected int distantaP=0;
	protected int distantaI=0;

	@SuppressWarnings("rawtypes")
	public Stack btStack=new Stack();

	public void adaugaRuta(String p, String d, boolean skip, int munte, int inclinat, int plat)
	{
		if(nrRute<MAX)
		{
			Ruta z=new Ruta(p, d, skip, munte, inclinat, plat);
			rute[nrRute]=z;
			nrRute++;
		}
		else 
			System.out.println("Nu mai poate fi adaugata nicio ruta!");

	}
	public void setup()
	{
		adaugaRuta("A", "C", false, 20,20,15);
		adaugaRuta("A", "I", false, 50,10,30);
		adaugaRuta("C", "D", false, 10,20,9);
		adaugaRuta("C", "F", false, 20,1,21);
		adaugaRuta("D", "E", false, 1,10,9);
		adaugaRuta("E", "J", false, 1,1,30);	
		adaugaRuta("E", "B", false, 20,30,2);
		adaugaRuta("F", "E", false, 1,20,21);
		adaugaRuta("F", "G", false, 50,1,1);
		adaugaRuta("J","B", false, 10,10,21);
		adaugaRuta("G","B", false, 1,1,60);	
		adaugaRuta("I", "J", false, 1,10,30);
		adaugaRuta("C", "A", false, 20,20,15);
		adaugaRuta("I", "A", false, 50,10,30);
		adaugaRuta("D", "C", false, 10,20,9);
		adaugaRuta("F", "C", false, 20,1,21);
		adaugaRuta("E", "D", false, 1,10,9);
		adaugaRuta("J", "E", false, 1,1,30);	
		adaugaRuta("B", "E", false, 20,30,1);
		adaugaRuta("E", "F", false, 1,20,21);
		adaugaRuta("G", "F", false, 50,1,1);
		adaugaRuta("B","J", false, 10,10,21);
		adaugaRuta("B","G", false, 1,1,60);	
		adaugaRuta("J", "I", false, 1,10,30);
			

	}
	
	//caut ruta inversa
	public Ruta cautInvers(String plecare, String destinatie)
	{
		Ruta a=null;
		for(int i=0;i< nrRute; i++)
		{
			if(rute[i].getLocalitatePlecare().equals(plecare) && rute[i].getLocalitateSosire().equals(destinatie))
				a=rute[i];
		}
		return a;
	}

	//verifica daca exista drum direct intre plecare si dest
	public int matchM(String plecare, String destinatie)
	{
		int dist=0;		
		for(int i=0;i< nrRute; i++)
		{
			if((rute[i].getLocalitatePlecare().equals(plecare)&& rute[i].isSkip()==false) && (rute[i].getLocalitateSosire().equals(destinatie)&& rute[i].isSkip()==false))
			{
				dist=rute[i].getMunte();
				//rute[i].setSkip(true);
			}
		}
		return dist;
	}

	
	public int matchI(String plecare, String destinatie)
	{
		int dist=0;		
		for(int i=0;i< nrRute; i++)
		{
			if((rute[i].getLocalitatePlecare().equals(plecare)&& rute[i].isSkip()==false) && (rute[i].getLocalitateSosire().equals(destinatie)&& rute[i].isSkip()==false))
			{
				dist=rute[i].getInclinat();
				//rute[i].setSkip(true);
			}
		}
		return dist;
	}
	
	public int matchP(String plecare, String destinatie)
	{
		int dist=0;		
		for(int i=0;i< nrRute; i++)
		{
			if((rute[i].getLocalitatePlecare().equals(plecare)&& rute[i].isSkip()==false) && (rute[i].getLocalitateSosire().equals(destinatie)&& rute[i].isSkip()==false))
			{
				dist=rute[i].getPlat();
				//rute[i].setSkip(true);
			}
		}
		return dist;
	}
	
	//caut ruta minima ce pleaca din from
	public Ruta findM(String from)
	{
		Ruta r=null, aux=null;
		int i=0, min=1000;
		i=0;
		while(i<nrRute )
		{
			if(rute[i].getLocalitatePlecare().equals(from) && rute[i].isSkip()==false)
			{
				r=new Ruta(from, rute[i].getLocalitateSosire(), rute[i].isSkip(), rute[i].getMunte(), rute[i].getInclinat(), rute[i].getPlat());
				if(min>r.getMunte())
				{ 
					min=r.getMunte();
					aux=r;
				}
			}
			i++;
		}
		return aux;
	}
	
	public Ruta findI(String from)
	{
		Ruta r=null, aux=null;
		int i=0, min=1000;
		i=0;
		while(i<nrRute )
		{
			if(rute[i].getLocalitatePlecare().equals(from) && rute[i].isSkip()==false)
			{
				r=new Ruta(from, rute[i].getLocalitateSosire(), rute[i].isSkip(), rute[i].getMunte(), rute[i].getInclinat(), rute[i].getPlat());
				if(min>r.getInclinat())
				{ 
					min=r.getInclinat();
					aux=r;
				}
			}
			i++;
		}
		return aux;
	}

	public Ruta findP(String from)
	{
		Ruta r=null, aux=null;
		int i=0, min=1000;
		i=0;
		while(i<nrRute )
		{
			if(rute[i].getLocalitatePlecare().equals(from) && rute[i].isSkip()==false)
			{
				r=new Ruta(from, rute[i].getLocalitateSosire(), rute[i].isSkip(), rute[i].getMunte(), rute[i].getInclinat(), rute[i].getPlat());
				if(min>r.getPlat())
				{ 
					min=r.getPlat();
					aux=r;
				}
			}
			i++;
		}
		return aux;
	}

	//alfa cea mai mica distanta dintre munte/inlcinat si plat
	public int match(String plecare, String destinatie)
	{
		int min;
		min=matchM(plecare, destinatie);
		if(min> matchI(plecare, destinatie))
			min=matchI(plecare, destinatie);
		else if(min> matchP(plecare, destinatie))
			min=matchP(plecare, destinatie);
			
		return min;
	}
	//cauta ruta care are plecare , destinatie si cel mai scurt drum dat
	public String ruta(String plecare, String destinatie, int d)
	{
		String a=null;
		int dist;
		dist=match(plecare, destinatie);
		for(int i=0;i< nrRute; i++)
		{
			if(rute[i].getLocalitatePlecare().equals(plecare) && rute[i].getLocalitateSosire().equals(destinatie) && dist==d)
			{
				if(rute[i].getInclinat()==dist)
					a="inclinat";
				if(rute[i].getMunte()==dist)
					a="munte";
				if(rute[i].getPlat()==dist)
					a="plat";
			}
		}
		
		return a;
		
	}
	
	//la fel ca ruta doar ca-mi intoarce ruta
	public Ruta ruta2(String plecare, String destinatie, int d)
	{
		Ruta b=null;
		int dist;
		dist=match(plecare, destinatie);
		for(int i=0;i< nrRute; i++)
		{
			if(rute[i].getLocalitatePlecare().equals(plecare) && rute[i].getLocalitateSosire().equals(destinatie) && dist==d)
			{
				b=rute[i];
			}
		}
		
		return b;
		
	}
	
	//calculeaza care e cea mai buna alegere: munte/inclinat/plat
	public Ruta find(String from)
	{
		Ruta a=null, b=null, c=null;
		a=findM(from);
		b=findI(from);
		c=findP(from);
		
		if(a.getMunte()<b.getInclinat())
			if(a.getMunte()<c.getPlat())
			{
				//a.setSkip(true);
				cautInvers(a.getLocalitatePlecare(), a.getLocalitateSosire()).setSkip(true);
				distantaM=distantaM + a.getMunte();
				//System.out.println("Pana in "+a.getLocalitateSosire()+" am parcurs "+a.getMunte()+ " pe drum de munte.");
				return a;
			}
			else
			{
				//c.setSkip(true);
				cautInvers(c.getLocalitatePlecare(), c.getLocalitateSosire()).setSkip(true);
				distantaP=distantaP + c.getPlat();
				//System.out.println("Pana in "+c.getLocalitateSosire()+" am parcurs "+c.getPlat()+" pe drum plat.");
				return c;
			}
		else
			if (b.getInclinat()<c.getPlat())
			{
				cautInvers(b.getLocalitatePlecare(), b.getLocalitateSosire()).setSkip(true);
				//b.setSkip(true);
				distantaI=distantaI + b.getInclinat();
				//System.out.println("Pana in "+b.getLocalitateSosire()+" am parcurs "+b.getInclinat()+" pe drum inclinat .");
				return b;
			}
			else 
			{
				cautInvers(c.getLocalitatePlecare(), c.getLocalitateSosire()).setSkip(true);
				//c.setSkip(true);
				distantaP=distantaP + c.getPlat();
				//System.out.println("Pana in "+c.getLocalitateSosire()+" am parcurs "+c.getPlat()+" pe drum plat.");
				return c;
			}		
	}
	
	
	@SuppressWarnings("unchecked")
	public void calculRuta(String from, String to)
	{
		
		Ruta z;
		if(match(from, to)>0)
		{
			Ruta aa, bb,cc;
			aa=find(from);
			bb=cautInvers(aa.getLocalitateSosire(),aa.getLocalitatePlecare());
			if(aa.getLocalitateSosire()==bb.getLocalitatePlecare() && bb.isSkip()==true)
			{
					
						aa.setSkip(true);
						System.out.println("Pana in "+to+" am parcurs " + match(from, to)+ " pe drum "+ruta(from, to, match(from, to)));
						System.out.println("Am ajuns la destinatie.");
						cc=ruta2(from, to, match(from, to));
						if(cc.getInclinat()==match(from, to))
									distantaI=distantaI+match(from, to);
						if(cc.getMunte()==match(from, to))
									distantaM=distantaM+match(from, to);
						if(cc.getPlat()==match(from, to))
									distantaP=distantaP+match(from, to);
							
						
						System.out.println("In total am de parcurs " + distantaM + " km pe tronson munte,"+ distantaI + " km pe tronson inclinat si "+ distantaP + " km pe tronson plat");
						return ;
					}
					else
					{
						btStack.push(aa);
						aa.setSkip(true);
						System.out.print("Pana in "+aa.getLocalitateSosire()+" am parcurs "+aa.getMunte()+ " pe drum de" );
						if(aa.getMunte()<aa.getInclinat())
							if(aa.getMunte()<aa.getPlat())
								System.out.println(" munte.");
							else
								System.out.println(" plat.");
						else
							if (aa.getInclinat()<aa.getPlat())
								System.out.println(" inclinat .");
							else 
								System.out.println(" plat.");
									
						calculRuta(aa.getLocalitateSosire(), to);
					}
		}
		else
		{


			z=find(from);
			if(z!=null)
			{
				btStack.push(z);
				z.setSkip(true);
				System.out.print("Pana in "+z.getLocalitateSosire()+" am parcurs ");
				if(z.getMunte()<z.getInclinat())
					if(z.getMunte()<z.getPlat())
						System.out.println(z.getMunte()+ " pe drum de munte.");
					else
						System.out.println(z.getInclinat()+ " pe drum inclinat.");
				else
					if (z.getInclinat()<z.getPlat())
						System.out.println(z.getInclinat()+ " pe drum inclinat.");
					else 
						System.out.println(z.getPlat()+ " pe drum plat.");
				
				
				//daca am ajuns la solutie
				if( z.getLocalitatePlecare().equals(to))
				{
					System.out.println("Am ajuns la destinatie.");
					System.out.println("In total am de parcurs " + distantaM + " km pe tronson munte,"+ distantaI + " km pe tronson inclinat si "+ distantaP + " km pe tronson plat");
					return;
				}
				else
					calculRuta(z.getLocalitateSosire(), to);
			}
			else
			{
				Ruta rr=(Ruta)btStack.pop();
				calculRuta(rr.getLocalitatePlecare(), to);
			}

		}


	}


}

